
package CPUfile::Intel;

use strict;

use vars qw($DEBUG);

$DEBUG = 0;
#
# Parse the /proc/cpuinfo file and return an one-liner characterizing the CPU
# This sub-module is the parsing code for Intel and compatible processors,
# including AMD and various more obscure clones.
#
# The information comes from the LInux kernel.
# On 2.4.27, x86 info is from arch/i386/kernel/setup.c, procedure show_cpuinfo
# Also implicated is asm/cpufeature.h, apparently.
#
#

# parsed version of cpufile
use vars qw(%keys);
# Model maps (initialized later)
use vars qw(%AMDmap %Intelmap);
use vars qw(%bogofactor);

sub parse {
    my $arch = shift; # architecture from uname()
    my $kernel = shift;
    my $cpufile = shift; # entire content of /proc/cpuinfo

    # TODO: need to count the processors here....
    
    my $cpu1file = $cpufile;
    $cpu1file =~ s/\n\n.*//; # look only at the first CPU
    my @lines = split("\n", $cpu1file);
    %keys = map {split(/\s+:\s/, $_)} @lines;
    
    my $cpuname = cpuname($kernel);
    return $cpuname . "/" . cpuspeed($cpuname, $cpufile);

}



sub cpuname {
    my $vendor = $keys{"vendor_id"};
    if ($vendor) {
	if ($vendor eq "AuthenticAMD") {
	    my $model = $AMDmap{$keys{"model name"}};
	    if (!$model) {
		warn "Unknown AMD model: " . $keys{"model name"} . "\n";
		return "AMD Unknown";
	    } else {
		return "AMD $model";
	    }
	} elsif ($vendor eq "GenuineIntel") {
	    my $model = $Intelmap{$keys{"model name"}};
	    if (!$model) {
		warn "Unknown Intel model: " . $keys{"model name"} . "\n";
		return "Intel Unknown";
	    } else {
		return "Intel $model";
	    }
	} else {
	    warn "Unknown vendor: $vendor\n";
	    return $vendor;
	}
    } else {
	return "No vendor_id";
    }
}

sub cpuspeed {
    my $cpuname = shift;
    if ($keys{"cpu MHz"}) {
	return int($keys{"cpu MHz"});
    } else {
	warn "no MHz\n";
	if ($bogofactor{$cpuname}) {
	    return $keys{"bogomips"} * $bogofactor{$cpuname};
	} else {
	    warn "No bogofactor for $cpuname\n";
	    return 0;
	}
    }
}


sub leftovercode {
    my $entry = shift;
    my $scriptversion;

    if ($$entry{method} =~ /machine-update version (\d.\d+)/) {
	$scriptversion = $1;
	if ($scriptversion < 0.17) {
	    return parsecpu_pre_17($$entry{cpu}, $$entry{kernel});
	} else {
	    return parsecpu_new($entry);
	}
    } else {
	warn "Unknown script ID: ", $$entry{method}, "\n";
	return "Hacked script/0";
    }
}

# Bogon factors - multipy bogomips with this to get MHz
%bogofactor =
    (
     "bogus CPU" => 5,
     );

# Model tables... for Intel and AMD, these are checked against cpu_model_name
use vars qw(%three86list %pentiumlist %four86list %p2list %p3list %pMlist
 %celeronlist %xeonlist %transmetalist %viatechlist %viac6list
 %athlonlist %am5xlist %am4list %k5list %k6list %k7list %duronlist %sempronlist
 %cx486list %cx586list %cx686list %p4list);


# Intel models
map {$Intelmap{$_} = '386'} (
"386 SX/DX", "386", "i386",
			     );
map {$Intelmap{$_} = '486'} (
"486 DX-50", "DX/4", "486 DX/2", "486 DX/4", "486 DX/2-WB", "486 DX/4-WB",
"486 SX", "486-SX25", "486DX2/66", "486", "i486",
"486 DX-2/80",
"486 DX-25/33",
"DX/2-WB",
"DX/2",
			     );
# Pentium variations
map {$Intelmap{$_} = 'Pentium'} (
"Pentium MMX",
"Pentium MMX 233Mhz",
"Pentium Pro",
"PPro/200",
"Pentium",
"Pentium 60/66",
"Pentium 75",
"Pentium 75+",
"Pentium 75 - 200",
"Pentium 90",
"Pentium 100",
"Pentium 120",
"Pentium 133",
"Pentium 150",
"Pentium 166",
"Pentium 166 MMX",
"Pentium 200",
"Pentium 200 MMX",
"Pentium Classic",
"Mobile Pentium 75 - 200",
"Mobile Pentium MMX",
			      );

map {$Intelmap{$_} = 'Pentium II'} (
"Pentium II (Klamath)",
"Pentium II (Deschutes)",
"Pentium II",
"Mobile Pentium II",
			 );

map {$Intelmap{$_} = 'Pentium III'} (
"Pentium III (Coppermine)",
"Pentium III (Katmai)",
"Pentium III",
"Pentium III (Cascades)",
"Pentium III (Coopermine)",
"Pentium III (on fire)",
"Pentium III (Coppermine) (666Mhz/133Mhz FSB)",
"Pentium III 666E",
"Intel(R) Pentium(R) III CPU              533MHz",
"Intel(R) Pentium(R) III CPU              733MHz",
"Intel(R) Pentium(R) III CPU             1133MHz",
"Intel(R) Pentium(R) III CPU             1200MHz",
"Intel(R) Pentium(R) III CPU - S         1133MHz",
"Intel(R) Pentium(R) III CPU - S         1266MHz",
"Intel(R) Pentium(R) III CPU - S         1400MHz",
"Intel(R) Pentium(R) III CPU family      1133MHz",
"Intel(R) Pentium(R) III CPU family      1266MHz",
"Intel(R) Pentium(R) III CPU family      1400MHz",
"Intel(R) Pentium(R) III Mobile CPU       800MHz",
"Intel(R) Pentium(R) III Mobile CPU       850MHz",
"Intel(R) Pentium(R) III Mobile CPU       866MHz",
"Intel(R) Pentium(R) III Mobile CPU       933MHz",
"Intel(R) Pentium(R) III Mobile CPU      1000MHz",
"Intel(R) Pentium(R) III Mobile CPU      1133MHz",
"Intel(R) Pentium(R) III Mobile CPU      1200MHz",
"Mobile Intel(R) Pentium(R) III CPU - M  1066MHz",
			 );
map {$Intelmap{$_} = 'Pentium M'} (
"Intel(R) Pentium(R) M processor 1300MHz",
"Intel(R) Pentium(R) M processor 1400MHz",
"Intel(R) Pentium(R) M processor 1500MHz",
"Intel(R) Pentium(R) M processor 1600MHz",
"Intel(R) Pentium(R) M processor 1.10GHz",
                         );
map {$Intelmap{$_} = 'Pentium 4'} (
"Intel(R) Pentium(R) 4 CPU 1.40GHz",
"Intel(R) Pentium(R) 4 CPU 1.50GHz",
"Intel(R) Pentium(R) 4 CPU 1.60GHz",
"Intel(R) Pentium(R) 4 CPU 1.70GHz",
"Intel(R) Pentium(R) 4 CPU 1.80GHz",
"Intel(R) Pentium(R) 4 CPU 1.90GHz",
"Intel(R) Pentium(R) 4 CPU 1300MHz",
"Intel(R) Pentium(R) 4 CPU 1400MHz",
"Intel(R) Pentium(R) 4 CPU 1500MHz",
"Intel(R) Pentium(R) 4 CPU 1600MHz",
"Intel(R) Pentium(R) 4 CPU 1700MHz",
"Intel(R) Pentium(R) 4 CPU 1800MHz",
"Intel(R) Pentium(R) 4 CPU 2.00GHz",
"Intel(R) Pentium(R) 4 CPU 2.20GHz",
"Intel(R) Pentium(R) 4 CPU 2.26GHz",
"Intel(R) Pentium(R) 4 CPU 2.40GHz",
"Intel(R) Pentium(R) 4 CPU 2.50GHz",
"Intel(R) Pentium(R) 4 CPU 2.53GHz",
"Intel(R) Pentium(R) 4 CPU 2.60GHz",
"Intel(R) Pentium(R) 4 CPU 2.66GHz",
"Intel(R) Pentium(R) 4 CPU 2.80GHz",
"Intel(R) Pentium(R) 4 CPU 3.00GHz",
"Intel(R) Pentium(R) 4 CPU 3.06GHz",
"Intel(R) Pentium(R) 4 CPU 3.20GHz",
"Intel(R) Pentium(R) 4 Mobile CPU 1.60GHz",
"Intel(R) Pentium(R) 4 Mobile CPU 1.70GHz",
"Intel(R) Pentium(R) 4 Mobile CPU 1.80GHz",
"Intel(R) Pentium(R) 4 Mobile CPU 2.00GHz",
"Mobile Intel(R) Pentium(R) 4 - M CPU 1.70GHz",
"Mobile Intel(R) Pentium(R) 4 - M CPU 1.80GHz",
"Mobile Intel(R) Pentium(R) 4 - M CPU 1.90GHz",
"Mobile Intel(R) Pentium(R) 4 - M CPU 2.00GHz",
"Mobile Intel(R) Pentium(R) 4 - M CPU 2.20GHz",
"Mobile Intel(R) Pentium(R) 4 - M CPU 2.40GHz",
"Pentium 4",
			 );
map {$Intelmap{$_} = 'Celeron'} (
"Celeron",
"Celeron (Coppermine)",
"Celeron (Mendocino)",
"Celeron (Covington)",
"Intel(R) Celeron(R) CPU 1.70GHz",
"Intel(R) Celeron(R) CPU 1.80GHz",
"Intel(R) Celeron(R) CPU 2.00GHz",
"Intel(R) Celeron(R) CPU 2.10GHz",
"Intel(R) Celeron(R) CPU 2.20GHz",
"Intel(R) Celeron(R) CPU 2.30GHz",
"Intel(R) Celeron(R) CPU 2.40GHz",
"Intel(R) Celeron(R) CPU 2.60GHz",
"Intel(R) Celeron(TM) CPU                1000MHz",
"Intel(R) Celeron(TM) CPU                1066MHz",
"Intel(R) Celeron(TM) CPU                1100MHz",
"Intel(R) Celeron(TM) CPU                1133MHz",
"Intel(R) Celeron(TM) CPU                1200MHz",
"Intel(R) Celeron(TM) CPU                1300MHz",
"Intel(R) Celeron(TM) CPU                1333MHz",
"Intel(R) Celeron(TM) CPU                1400MHz",
"Mobile Celeron",
"Mobile Intel(R) Celeron(R) CPU 1.80GHz",
"Mobile Intel(R) Celeron(TM) CPU         1133MHz",
"Mobile Intel(R) Celeron(TM) CPU         1200MHz",
"Mobile Intel(R) Celeron(TM) CPU         1333MHz",
"Intel(R) Celeron(R) M processor         1.30GHz",
"Intel(R) Celeron(R) M processor         1.40GHz",
			 );
map {$Intelmap{$_} = 'Xeon'} (
"Intel(R) XEON(TM) CPU 1.80GHz",
"Intel(R) XEON(TM) CPU 2.00GHz",
"Intel(R) XEON(TM) CPU 2.20GHz",
"Intel(R) XEON(TM) CPU 2.40GHz",
"Intel(R) Xeon(TM) CPU 1.40GHz",
"Intel(R) Xeon(TM) CPU 1.50GHz",
"Intel(R) Xeon(TM) CPU 1.70GHz",
"Intel(R) Xeon(TM) CPU 1.80GHz",
"Intel(R) Xeon(TM) CPU 1400MHz",
"Intel(R) Xeon(TM) CPU 1700MHz",
"Intel(R) Xeon(TM) CPU 2.00GHz",
"Intel(R) Xeon(TM) CPU 2.20GHz",
"Intel(R) Xeon(TM) CPU 2.40GHz",
"Intel(R) Xeon(TM) CPU 2.60GHz",
"Intel(R) Xeon(TM) CPU 2.80GHz",
"Intel(R) Xeon(TM) CPU 3.00GHz",
"Intel(R) Xeon(TM) CPU 3.06GHz",
                         );
%transmetalist = map {$_ => 1} (
"Transmeta(tm) Crusoe(tm) Processor TM5500",
"Transmeta(tm) Crusoe(tm) Processor TM5600",
"Transmeta(tm) Crusoe(tm) Processor TM5800",
                             );
%viatechlist = map {$_ => 1} (
"VIA C3 Ezra",
"VIA Ezra",
"VIA Nehemiah",
"VIA Samuel",
"VIA Samuel 2",

                             );

%viac6list = map {$_ => 1} (
"WinChip 2A",
"WinChip C6",
"C6",
"C6-2",
                             );
# AMD models
map {$AMDmap{$_} = "Athlon"} (
"Athlon",
"Athlon XP",
"AMD Athlon(tm) Processor",
"AMD Athlon(tm) processor",
"AMD Athlon(TM)Processor",
"AMD Athlon(tm) ",
"AMD Athlon(tm) 4 Processor",
"AMD Athlon(tm) 4 processor",
"AMD Athlon(tm) 64 Processor 2800+",
"AMD Athlon(tm) 64 Processor 3000+",
"AMD Athlon(tm) 64 Processor 3200+",
"AMD Athlon(tm) 64 Processor 3400+",
"AMD Athlon(tm) MP Processor 1800+",
"AMD Athlon(tm) MP Processor 1900+",
"AMD Athlon(tm) MP processor",
"AMD Athlon(tm) Processor",
"AMD Athlon(tm) Prosussor", #!!!!!!!!!!
"AMD Athlon(tm) XP",
"AMD Athlon(tm) XP  2600+",
"AMD Athlon(tm) XP processor 1700+",
"AMD Athlon(tm) XP processor 1800+",
"AMD Athlon(tm) XP Processor 2100+",
"AMD Athlon(tm)",
"AMD Athlon",
"AMD Athlon (TM)",
"AMD Athlon(TM) MP 1600+",
"AMD Athlon(TM) MP 1800+",
"AMD Athlon(TM) MP 1900+",
"AMD Athlon(TM) MP 2000+",
"AMD Athlon(tm) MP",
"AMD Athlon(tm) MP 1500+",
"AMD Athlon(tm) MP 1800+",
"AMD Athlon(tm) MP 2000+",
"AMD Athlon(tm) MP 2400+",
"AMD Athlon(tm) MP 2600+",
"AMD Athlon(TM) XP",
"AMD Athlon(tm) XP ",
"AMD Athlon(TM) XP 1500+",
"AMD Athlon(TM) XP 1600+",
"AMD Athlon(TM) XP 1700+",
"AMD Athlon(TM) XP 1800+",
"AMD Athlon(TM) XP 1900+",
"AMD Athlon(TM) XP 2000+",
"AMD Athlon(TM) XP 2100+",
"AMD Athlon(TM) XP 2200+",
"AMD Athlon(TM) XP 2400+",
"AMD Athlon(TM) XP 2500+",
"AMD Athlon(TM) XP 2600+",
"AMD Athlon(TM) XP 2800+",
"AMD Athlon(TM) XP1500+",
"AMD Athlon(TM) XP1600+",
"AMD Athlon(TM) XP1700+",
"AMD Athlon(TM) XP1800+",
"AMD Athlon(TM) XP1900+",
"AMD Athlon(TM) XP2000+",
"AMD Athlon(TM) XP2100+",
"AMD Athlon(tm) XP",
"AMD Athlon(tm) XP 1500+",
"AMD Athlon(tm) XP 1600",
"AMD Athlon(tm) XP 1600+",
"AMD Athlon(tm) XP 1700+",
"AMD Athlon(tm) XP 1800+",
"AMD Athlon(tm) XP 1900+",
"AMD Athlon(tm) XP 2000+",
"AMD Athlon(tm) XP 2000+ ",
"AMD Athlon(tm) XP 2100+",
"AMD Athlon(tm) XP 2200+",
"AMD Athlon(tm) XP 2400+",
"AMD Athlon(tm) XP 2500+",
"AMD Athlon(tm) XP 2600+",
"AMD Athlon(tm) XP 2700+",
"AMD Athlon(tm) XP 2800+",
"AMD Athlon(tm) XP 3000+",
"AMD Athlon(tm) XP 3200+",
"Mobile AMD Athlon(tm) 4 Processor",
"mobile AMD Athlon (tm) 1400+",
"mobile AMD Athlon(tm) 4",
"mobile AMD Athlon(tm) 4  1600+",
"mobile AMD Athlon(tm) 4 1500+",
"mobile AMD Athlon(tm) 4 1600+",
"mobile AMD Athlon(tm) 4 Processor",
"mobile AMD Athlon(tm) 4 processor",
"mobile AMD Athlon(tm) XP 1400+",
"mobile AMD Athlon(tm) XP 1400+  ",
"mobile AMD Athlon(tm) XP 1400+",
"mobile AMD Athlon(tm) XP 1500+",
"mobile AMD Athlon(tm) XP 1600+",
"mobile AMD Athlon(tm) XP 1700+",
"mobile AMD Athlon(tm) XP 2000+",
"mobile AMD Athlon(tm) XP 2200+",
"mobile AMD Athlon(tm) XP-M 2400+",
"mobile AMD Athlon(tm) XP2000+",
"2xAMD Athlon(TM) MP 1800+",
			     );
map {$AMDmap{$_} = "5x86"} (
"Am5x86-WB", "Am5x86-WT",
			  );

map {$AMDmap{$_} = "486"} (
"486 DX/4", "486 DX/4-WB", "DX/4-WB", "486dx2/66",
			     );
map {$AMDmap{$_} = "Duron"} (
"AMD Duron(TM)",
"AMD Duron(tm)",
"AMD Duron(tm) ",
"AMD Duron(tm)          ",
"AMD Duron",
"AMD Duron(TM)Processor",
"AMD Duron(tm) Processor",
"AMD Duron(tm) Processor ",
"AMD Duron(tm) processor",
"Mobile AMD Duron(tm) Processor",
"mobile AMD  Duron(tm)",
"mobile AMD Duron(tm)",
"mobile AMD Duron(tm) Processor",
"mobile AMD Duron(tm) 4",
			     );
map {$AMDmap{$_} = "K5"} (
"AMD-K5(tm) Processor",
"K5/SSA5",
                         );
map {$AMDmap{$_} = "K6"} (
"AMD-K6(tm) 3D processor", "AMD-K6tm w/ multimedia extensions",
"AMD-K6(tm)-III Processor", "AMD-K6(tm) 3D+ Processor", "AMD K6/133", "K6-2",
			 );
map {$AMDmap{$_} = "K7"} (
"AMD-K7(tm) Processor",
"AMD K7 processo",
			 );

map {$AMDmap{$_} = "Sempron"} (
"AMD Sempron(tm) 2200+",
"AMD Sempron(tm)   2500+",
			      );

# Cyrix processors

%cx486list = map {$_ => 1} (
"Cx486DX",
"Cx486DX2", # Nick Warne
"Cx486DX4",
"Cx486SLC",
                         );
%cx686list = map {$_ => 1} (
"5x86 3x Core/Bus Clock",
"6x86MX 2x Core/Bus Clock",
"6x86MX 2.5x Core/Bus Clock",
"6x86 2x Core/Bus Clock",
"6x86L 2x Core/Bus Clock",
"6x86L 3x Core/Bus Clock",
"6x86MX 3x Core/Bus Clock",
"6x86L",
"Cyrix MediaGXtm MMXtm Enhanced",
"M II 3.5x Core/Bus Clock",
"M II 3x Core/Bus Clock",
"M II 2.5x Core/Bus Clock",
"M II 2x Core/Bus Clock",
			    );
%cx586list = map {$_ => 1} (
			    );

sub parsecpu {

    my $entry = shift;

    my $processors = $$entry{"processors"};
    my $kernel = $$entry{kernel};
    my $cpu;
    $DEBUG && dumpcpudata($entry);
    if ($kernel =~ /^2.[23456]/) {
	if ($$entry{cpu_vendor} eq "GenuineIntel" || $$entry{cpu_vendor} eq "Intel") {
	    if ($pentiumlist{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Intel Pentium/$mhz";
	    } elsif ($four86list{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{bogomips} * 3.9783);
		$cpu = "Intel 486/$mhz";
	    } elsif ($p4list{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Intel Pentium4/$mhz";
	    } elsif ($pMlist{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Intel Pentium M/$mhz";
	    } elsif ($p3list{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Intel PentiumIII/$mhz";
	    } elsif ($p2list{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Intel PentiumII/$mhz";
	    } elsif ($celeronlist{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Intel Celeron/$mhz";
	    } elsif ($xeonlist{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Intel Xeon/$mhz";
	    } elsif ($three86list{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{bogomips} * 5.0925);
		$cpu = "Intel 386/$mhz";
	    } elsif ($three86list{$$entry{cpu_model}}) {
		# from a 2.0.36 kernel
		my $mhz = int($$entry{bogomips} * 5.0925);
		$cpu = "Intel 386/$mhz";
	    } elsif ($pentiumlist{$$entry{cpu_model}}) {
		# at least 1 occurence has model in cpu_model, not _name
		# this is from a 2.2.15 kernel, and has no MHZ.
		my $mhz = int($$entry{bogomips} * 5); # FIXME - random number
		$cpu = "Intel Pentium/$mhz";
	    } elsif ($four86list{$$entry{cpu_model}}) {
		# from a 2.0.36 kernel
		my $mhz = int($$entry{bogomips} * 3.9783);
		$cpu = "Intel 486/$mhz";
	    } elsif ($$entry{cpu_model_name} =~ /^OverDrive/) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Intel OverDrive/$mhz";
	    } elsif ($$entry{cpu_uname} eq "i386") {
		# Fallback for 386es - some of these have "unknown" in model
		my $mhz = int($$entry{bogomips} * 5.0925);
		$cpu = "Intel 386/$mhz";
	    } elsif ($$entry{cpu_uname} eq "i486") {
		# Fallback for 486es - some of these have "unknown" in model
		my $mhz = int($$entry{bogomips} * 5.0925);
		$cpu = "Intel 486/$mhz";
 	    } elsif ($$entry{cpu_uname} eq "i586") {
		# Reported from a 2.4.10 kernel - MHZ 133... old?
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Intel 586/$mhz";
 	    } elsif ($$entry{cpu_uname} eq "i686") {
		# Reported from a 2.2.10 kernel - model 00/07 - weird!
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Intel 686/$mhz";
	    } else {
		dumpcpudata($entry);
		$cpu = "UNPARSED (Intel Unknown)";
	    }
	} elsif (($$entry{cpu_vendor} eq "AuthenticAMD")
		|| ($$entry{cpu_vendor} eq "Authentic AMD")
		|| ($$entry{cpu_vendor} eq "AMD")) {
 	    if ($athlonlist{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "AMD Athlon/$mhz";
 	    } elsif ($duronlist{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "AMD Duron/$mhz";
	    # TODO: Check those bogofactors!!!!!!!!
	    } elsif ($k5list{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{bogomips} * 3.9783);
		$cpu = "AMD K5/$mhz";
	    } elsif ($k6list{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{bogomips} * 3.9783);
		$cpu = "AMD K6/$mhz";
	    } elsif ($k7list{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "AMD K7/$mhz";
	    } elsif ($sempronlist{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "AMD Sempron/$mhz";
	    } elsif ($am5xlist{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{bogomips} * 3.9783);
		$cpu = "AMD 5x86/$mhz";
	    } elsif ($am4list{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{bogomips} * 3.9783); # FIXME - random
		$cpu = "AMD 486/$mhz";
            } elsif ($$entry{cpu_model_name} eq "Unknown CPU Type") {
		# strange report from a 2.6.8 kernel
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "AMD 686/$mhz";
            } elsif ($$entry{cpu_model_name} eq "n") {
		# strange report from a 2.4.10 kernel
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "AMD " . $$entry{cpu_uname} . "/$mhz";
	    } elsif ($p3list{$$entry{cpu_model_name}}) {
		# At least one CPU with Intel model name and AMD as vendor
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "AMD Pentium/$mhz";
	    } else {
		dumpcpudata($entry);
		$cpu = "UNPARSED (AMD Unknown)";
	    }
	} elsif ($$entry{cpu_vendor} eq "CyrixInstead") {
	    if ($cx686list{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Cyrix 6x86/$mhz";
	    } elsif ($cx486list{$$entry{cpu_model_name}}) {
		# based on info from Nick Warne
		my $mhz = int($$entry{bogomips} * 66/26.62);
		$cpu = "Cyrix 486/$mhz";
            } else {
		dumpcpudata($entry);
		$cpu = "UNPARSED (Cyrix unknown)";
	    }
	} elsif ($$entry{cpu_vendor} eq "Cyrex") {
	    # still not completely convinced this is not an alias for Cyrix
	    # seems to use Intel-compatible markings
	    if ($pentiumlist{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Cyrex Pentium/$mhz";
	    } else {
		dumpcpudata($entry);
		$cpu = "UNPARSED (Cyrex unknown)";
	    }
	} elsif ($$entry{cpu_vendor} eq "CentaurHauls") {
	    # a quick Google says this CPU is from VIA
	    if ($viac6list{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{bogomips} * 5);
		$cpu = "VIA C6/$mhz";
	    } elsif ($viatechlist{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "VIA/$mhz"; # suppress model diffs
	    } else {
		dumpcpudata($entry);
		$cpu = "UNPARSED (VIA unknown)";
	    }
	} elsif ($$entry{cpu_vendor} eq "IBM/S390") {
	    # seems to be no speed-relevant info in record
	    $cpu = "IBM S390/42";
	} elsif ($$entry{cpu_vendor} eq "GenuineTMx86") {
	    if ($transmetalist{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Transmeta/$mhz";
	    } else {
		dumpcpudata($entry);
		$cpu = "UNPARSED (Transmeta unknown)";
	    }
	    
    } elsif ($kernel =~ /^2.0/ || $kernel =~ /^1.[23]/) {
	if ($$entry{cpu_vendor} eq "GenuineIntel") {
	    if ($pentiumlist{$$entry{cpu_model}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Intel Pentium/$mhz";
	    } elsif ($four86list{$$entry{cpu_model}}) {
		my $mhz = int($$entry{bogomips} * 3.9783);
		$cpu = "Intel 486/$mhz";
	    } elsif ($p3list{$$entry{cpu_model}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Intel PentiumIII/$mhz";
	    } elsif ($celeronlist{$$entry{cpu_model}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Intel Celeron/$mhz";
	    } elsif ($three86list{$$entry{cpu_model_name}}) {
		my $mhz = int($$entry{bogomips} * 5.0925);
		$cpu = "Intel 386/$mhz";
	    } elsif ($p2list{$$entry{cpu_model}}) {
		my $mhz = int($$entry{bogomips} * 5.0925);
		$cpu = "Intel PentiumII/$mhz";
	    } elsif ($three86list{$$entry{cpu_model}}) {
		# 2.0.36 kernel
		my $mhz = int($$entry{bogomips} * 5.0925);
		$cpu = "Intel 386/$mhz";
	    } elsif ($$entry{cpu_only} eq "586") {
		my $mhz = int($$entry{bogomips} * 5);
		$cpu = "Intel 586/$mhz"; # 2.0.34 kernel
	    } else {
		dumpcpudata($entry);
		$cpu = "UNPARSED (Intel Unknown)";
	    }
	} elsif ($$entry{cpu_vendor} eq "AuthenticAMD"
		 || ($$entry{cpu_vendor} eq "amd")) {
	    if ($athlonlist{$$entry{cpu_model}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "AMD Athlon/$mhz";
	    } elsif ($k5list{$$entry{cpu_model}}) {
		my $mhz = int($$entry{bogomips} * 3.9783);
		$cpu = "AMD K5/$mhz";
	    } elsif ($k6list{$$entry{cpu_model}}) {
		my $mhz = int($$entry{bogomips} * 3.9783);
		$cpu = "AMD K6/$mhz";
	    } elsif ($k7list{$$entry{cpu_model}}) {
		my $mhz = int($$entry{bogomips} * 3.9783);
		$cpu = "AMD K7/$mhz";
	    } elsif ($am4list{$$entry{cpu_model}}) {
		my $mhz = int($$entry{bogomips} * 3.9783);
		$cpu = "AMD 486/$mhz";
	    } elsif ($pentiumlist{$$entry{cpu_model}}) {
		# some AMD cpus were marked pentium - before trademark?
		my $mhz = int($$entry{bogomips} * 3.9783);
		$cpu = "AMD Pentium/$mhz";
	    } elsif ($$entry{cpu_uname} eq "i686") {
		# deficent information - 2.0.28
		my $mhz = int($$entry{bogomips} * 3.9783);
		$cpu = "AMD 686/$mhz";
	    } else {
		dumpcpudata($entry);
		$cpu = "UNPARSED (AMD Unknown)";
	    }
	} elsif ($$entry{cpu_vendor} eq "AMD") {
	    if ($$entry{cpu_model_name} eq "AMD 386") {
		# cpu_mhz from an 1.2.10 kernel...
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "AMD 386/$mhz";
	    } else {
		dumpcpudata($entry);
		$cpu = "UNPARSED (AMD2 Unknown)";
	    }
	} elsif ($$entry{cpu_vendor} eq "CyrixInstead") {
	    if ($cx686list{$$entry{cpu_model}}) {
		my $mhz = int($$entry{cpu_mhz});
		$cpu = "Cyrix 6x86/$mhz";
	    } elsif ($cx486list{$$entry{cpu_model}}) {
		# based on info from Nick Warne
		my $mhz = int($$entry{bogomips} * 66/26.62);
		$cpu = "Cyrix 486/$mhz";
            } else {
		dumpcpudata($entry);
		$cpu = "UNPARSED (Cyrix unknown)";
	    }
	} elsif ($$entry{cpu_only} eq "Alpha") {
	    my $mhz = int($$entry{cpu_hz}/1000000);
	    $cpu = "Alpha $$entry{cpu_model}/$mhz";
	} elsif ($$entry{cpu_only} eq "386") {
	    my $mhz = int($$entry{bogomips} * 5.0925);
	    $cpu = "Intel 386/$mhz";
	} elsif ($$entry{cpu_only} eq "486" && $$entry{cpu_vendor} eq "unknown") {
	    my $mhz = int($$entry{bogomips} * 5.0925);
	    $cpu = "Unknown 486/$mhz";
	} elsif ($$entry{cpu_uname} eq "mips") {
	    $cpu = parse_mips($entry);
	} elsif ($$entry{cpu_uname} eq "ppc"
		 && $$entry{cpu_machine} eq "PowerMac") {
	    # from a 2.0.33-osfmach3 kernel
	    my $mhz = 42;
	    $cpu = "PowerMac/$mhz";
	} else {
	    dumpcpudata($entry);
	    $cpu = "UNPARSED (Unknown vendor - kernel $kernel)";
	}
    } elsif ($kernel !~ /^\d\.\d+/ || $kernel =~ /^[567]/) {
	$cpu = "Broken Kernel $kernel/42";
    } else {
	dumpcpudata($entry);
	$cpu = "UNPARSED (Kernel $kernel)\n";
    }
    if ($processors > 1) {
	$cpu = $processors . "x " . $cpu;
    }
    return $cpu;
    }
}

sub dumpcpudata {
    my $entry = shift;
    my $x;
    warn "------------\n";
    for $x (keys(%$entry)) {
	warn "$x:<$$entry{$x}>\n" if $x =~ /^cpu/ 
	    || $x eq "kernel" || $x eq "bogomips";
    }
}

1;
